/**
 * Created by jinxs on 14-6-25.
 */
(function ($) {
    /**
     * 缓存名称
     * @type {string}
     * @private
     */
    var _cacheName = 'uiTooltip';

    /**
     * @class 提示信息组件
     * @constructor uiTooltip
     * @summary 构造函数
     * @param [options] {Object|String} 组件配置参数|要调用的组件方法名
     * @param [param] {Object} 表示要调用的组件方法的参数
     * @example
     *  //采用默认值
     * $('#scb').uiTooltip();
     * //设置组件参数
     *  $('#scb').uiTooltip({region:'right'});
     * //调用组件方法
     * $('#scb').uiTooltip('hide');
     */
    $.fn.uiTooltip = function (options, param) {
        if (typeof options == "string") {
            return $.fn.uiTooltip.methods[options](this, param);
        }
        return this.each(function(){
            var me = $(this);
            var cache = me.data(_cacheName);

            options = options || {};
            if (cache) {
                $.extend(cache.options, options);
            } else {
                me.data(_cacheName, {
                    options: $.extend({}, $.fn.uiTooltip.defaults, me.parseUIConfig(), options),
                    tip: null
                });
                _init(me);
            }
            _bindEvent(me);
            _update(me);
        });
    };
    /**
     * 方法
     * @lends uiTooltip.prototype
     */
    $.fn.uiTooltip.methods = {
        /**
         * @summary 获取所有配置
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        options: function (target) {
            return $.data(target[0], _cacheName).options;
        },
        /**
         * @summary 获取提示jquery对象
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        tip: function (target) {
            return $.getByParentID(target.getElemID(), $.uiTemplate.tooltip.tip);
        },
        /**
         * @summary 获取提示箭头jquery对象
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        arrow: function (target) {
            return target.uiTooltip("tip").children(".ui_tooltip-arrow-outer,.ui_tooltip-arrow");
        },
        /**
         * @summary 获取提示内容jquery对象
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        content: function (target) {
            return $.getByParentID($(target).getElemID(), $.uiTemplate.tooltip.content);
        },
        /**
         * @summary 显示提示
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        show: function (target, e) {
            _show(target, e);
        },
        /**
         * @summary 隐藏提示
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        hide: function (target, e) {
            _hide(target, e);
        },
        /**
         * @summary 更新提示
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        update: function (target, content) {
            _update(target, content);
        },
        /**
         * @summary 重置提示框位置。
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        reposition: function (target) {
            _reposition(target);
        },
        /**
         * @summary 删除提示对象
         * @param target
         * @returns {*|Function|HTMLOptionsCollection|options|options}
         */
        destroy: function (target) {
            _destroy(target);
        }
    };
    /**
     * 默认配置
     * @lends uiTooltip.prototype
     */
    $.fn.uiTooltip.defaults = {
        /**
         * @type String
         * @default 'right'
         * @summary 消息框位置。可用值有："left","right","top","bottom"
         */
        region: "right",
        /**
         * @type String|Object
         * @default null
         * @summary 消息框内容
         */
        content: null,
        /**
         * @type Boolean
         * @default false
         * @summary 为true时，允许提示框跟着鼠标移动
         */
        trackMouse: false,
        /**
         * @type Array
         * @default [0,0]
         * @summary [水平方向提示框的位置,垂直方向提示框的位置]
         */
        offset: [0, 0],
        /**
         * @type String
         * @default mouseenter
         * @summary 触发提示显示的事件
         */
        showOn: "mouseenter",
        /**
         * @type String
         * @default mouseleave
         * @summary 触发提示隐藏的事件
         */
        hideOn: "mouseleave",
        /**
         * @type Boolean
         * @default true
         * @summary 为false时，通过程序控制其隐藏
         */
        autoHide: true,
        /**
         * @type Boolean
         * @default true
         * @summary 为false时，通过程序控制其显示
         */
        autoShow:true,
        /**
         * @type Number
         * @default 200
         * @summary 延时多少秒显示提示框
         */
        showDelay: 200,
        /**
         * @type Number
         * @default 100
         * @summary 延时多少秒隐藏提示框
         */
        hideDelay: 100,
        /**
         * @event
         * @name uiTooltip#onShow
         * @type function
         * @default function () { }
         * @summary 在显示提示框的时候触发。
         */
        onShow: function (e) {
        },
        /**
         * @event
         * @name uiTooltip#onHide
         * @type function
         * @default function () { }
         * @summary 在隐藏提示框的时候触发。
         */
        onHide: function (e) {
        },
        /**
         * @event
         * @name uiTooltip#onUpdate
         * @type function
         * @default function () { }
         * @summary 在提示框内容更新的时候触发。
         */
        onUpdate: function (content) {
        },
        /**
         * @event
         * @name uiTooltip#onPosition
         * @type function
         * @default function () { }
         * @summary 在提示框位置改变的时候触发。
         */
        onPosition: function (left, top) {
        },
        /**
         * @event
         * @name uiTooltip#onDestroy
         * @type function
         * @default function () { }
         * @summary 在提示框被销毁的时候触发。
         */
        onDestroy: function () {
        }
    };
    //////--------------------------------内部方法------------------------------
    /**
     * 初始化方法，主要设置高宽，加载内容
     */
    var _init = function (target) {
        var state = $.data(target[0], _cacheName);
        var options = state.options;
        target.setElemID();
        var title = target.attr('title');
        if (title != undefined && title != '' && !options.content) {
            options.content = title;
            target.removeAttr('title');
        }
        return target;
    };

    function _show(target, e) {
        var state = $.data(target[0], _cacheName);
        var options = state.options;
        var tip = $.getByParentID(target.getElemID(), $.uiTemplate.tooltip.tip);
        if (tip.length == 0) {
            var targetID = target.getElemID();
            var reg = new RegExp('({target})', 'g');
            tip = $($.uiTemplate.tooltip.html.replace(reg, targetID)).appendTo('body');
            _update(target);
        }
        tip.removeClass("ui_tooltip-top ui_tooltip-bottom ui_tooltip-left ui_tooltip-right").addClass("ui_tooltip-" + options.region);
        _setTimer(target);
        state.showTimer = setTimeout(function () {
            _reposition(target);
            tip.show();
            options.onShow.call(target, e);
            var arrowOuter = $.getByParentID(targetID, $.uiTemplate.tooltip.tipAouter);
            var arrow = $.getByParentID(targetID, $.uiTemplate.tooltip.arrow);
            var borderColor = "border-" + options.region + "-color";
            arrowOuter.add(arrow).css({
                borderTopColor: "",
                borderBottomColor: "",
                borderLeftColor: "",
                borderRightColor: ""
            });
            arrowOuter.css(borderColor, tip.css(borderColor));
            arrow.css(borderColor, tip.css("backgroundColor"));
        }, options.showDelay);
        tip.unbind('mouseover.uiTooltip').bind('mouseover.uiTooltip', function (e) {
            if (state.hideTimer) {
                clearTimeout(state.hideTimer);
                state.hideTimer = null;
            }
        });
        if (options.autoHide) {
            tip.unbind('mouseleave.uiTooltip').bind('mouseleave.uiTooltip', function (e) {
                setTimeout(function () {
                    _hide(target, e);
                }, options.hideDelay);
            });
        }
    };
    function _bindEvent(target) {
        var state = $.data(target[0], _cacheName);
        var options = state.options;
        target.unbind(".uiTooltip");
        if (options.autoShow) {
            target.bind(options.showOn + ".uiTooltip", function (e) {
                _show(target, e);
            });
        }
        if (options.autoHide) {
            target.bind(options.hideOn + ".uiTooltip", function (e) {
                _hide(target, e);
            });
        }
        target.bind("mousemove.uiTooltip", function (e) {
            if (options.trackMouse) {
                options.trackMouseX = e.pageX;
                options.trackMouseY = e.pageY;
                _reposition(target);
            }
        });
    };
    function _setTimer(target) {
        var state = $.data(target[0], _cacheName);
        if (state.showTimer) {
            clearTimeout(state.showTimer);
            state.showTimer = null;
        }
        if (state.hideTimer) {
            clearTimeout(state.hideTimer);
            state.hideTimer = null;
        }
    };
    function _reposition(target) {
        var state = $.data(target[0], _cacheName);
        var tip = $.getByParentID(target.getElemID(), $.uiTemplate.tooltip.tip);
        if (!state || tip.length == 0) {
            return;
        }
        var options = state.options;
        var left, top, t;
        if (options.trackMouse) {
            t = $();
            left = options.trackMouseX + options.offset[0];
            top = options.trackMouseY + options.offset[1];
        } else {
            var t = $(target);
            left = t.offset().left + options.offset[0];
            top = t.offset().top + options.offset[1];
        }
        switch (options.region) {
            case $.uiTemplate.tooltip.region.right:
                left += t.outerWidth() + 12 + (options.trackMouse ? 12 : 0);
                top -= (tip.outerHeight() - t.outerHeight()) / 2;
                break;
            case $.uiTemplate.tooltip.region.left:
                left -= tip.outerWidth() + 12 + (options.trackMouse ? 12 : 0);
                top -= (tip.outerHeight() - t.outerHeight()) / 2;
                break;
            case $.uiTemplate.tooltip.region.top:
                left -= (tip.outerWidth() - t.outerWidth()) / 2;
                top -= tip.outerHeight() + 12 + (options.trackMouse ? 12 : 0);
                break;
            case $.uiTemplate.tooltip.region.bottom:
                left -= (tip.outerWidth() - t.outerWidth()) / 2;
                top += t.outerHeight() + 12 + (options.trackMouse ? 12 : 0);
                break;
        }
        if (!$(target).is(":visible")) {
            left = -100000;
            top = -100000;
        }
        tip.css({
            left: left,
            top: top,
            zIndex: (options.zIndex != undefined ? options.zIndex : ($.fn.uiDialog ? $.fn.uiDialog.defaults.zIndex++ : ""))
        });
        options.onPosition.call(target, left, top);
    };
    function _hide(target, e) {
        var state = $.data(target[0], _cacheName);
        var tip = $.getByParentID(target.getElemID(), $.uiTemplate.tooltip.tip);
        if (state && tip.length > 0) {
            _setTimer(target);
            state.hideTimer = setTimeout(function () {
                var tip = $.getByParentID(target.getElemID(), $.uiTemplate.tooltip.tip);
                tip.hide();
                state.options.onHide.call(target, e);
            }, state.options.hideDelay);
        }
    };
    function _update(target, content) {
        var state = $.data(target[0], _cacheName);
        var options = state.options;
        if (content) {
            options.content = content;
        }
        var tip = $.getByParentID(target.getElemID(), $.uiTemplate.tooltip.tip);
        if (tip.length == 0) {
            return;
        }
        var cont = typeof options.content == "function" ? options.content.call(target) : options.content;
        $.getByParentID($(target).getElemID(), $.uiTemplate.tooltip.content).html(cont);
        options.onUpdate.call(target, cont);
    };
    function _destroy(target) {
        var state = $.data(target[0], _cacheName);
        if (state) {
            _setTimer(target);
            var options = state.options;
            var tip = $.getByParentID(target.getElemID(), $.uiTemplate.tooltip.tip);
            if (tip.length > 0) {
                tip.remove();
            }
            if (options.content) {
                $(target).attr("title", options.content);
            }
            $.removeData(target, _cacheName);
            $(target).unbind(".uiTooltip");
            options.onDestroy.call(target);
        }
    };
})(jQuery);
